#ifndef HASH_SECUNDARIO_H_
#define HASH_SECUNDARIO_H_

/**********************************************************************
 * hash_secundario.h
 * 
 * Descripcion: Esta clase representa un archivo de datos que almacena
 * registros de indice secundario, y los accede mediante un hash extensible
 * con area de overflow para reg con la misma clave secundaria.
*********************************************************************/

#include "hash.h"
#include "indice_sec.h"
#include "debugger.h"
#include "excep_consulta_hash.h"
#include "arch_overflow.h"
#include "archivosFactory.h"

#define EXT_OFLW ".ofw"

class HashSec : public IndiceSec {

	//Atributos del archivo de hash
	private:
		
		Hash* arch_hash; //Archivo de Hash. Contiene claves unicas de un campo que no es unico y ref al arch de overflow.
		ArchOverflow* arch_oflow; //Archivo que contiene los datos referentes a cada clave, encadenados.
		
		//Constructor de copia privado para que no se pueda copiar un archivo
		HashSec(HashSec &s);
		
	public:
	
		HashSec(std::string& nombre, unsigned int tam_bloque, unsigned int tam_bloque_indice, unsigned int num_campo_clave);
	
		~HashSec();
	
		//////////////////////////////////////////////////////////////
		
		//Metodos heredados de la interfaz de archivo
		
		void abrir() throw(ExcepAbriendoArch);
		
		void crear(std::string formato) throw(ExcepCreandoArch, ExcepSintaxisParser, ExcepBloqueTam);
		
		void cerrar();
		
 		TiposArchivo get_tipo_archivo();		
 		
 		void eliminar ();		
 		
 		/*
 		 * Devuelve el tamanio libre del archivo en cantidad de bytes.
 		 */
 		unsigned int get_espacio_libre() throw(ExcepArchCerrado, ExcepLeerBloque);
 		
 		////////////////////////////////////////////////////////////////
 		
 		/*
 		 * Ingresar: Dado un registro completo, obtiene los campos necesarios para el
 		 * ind secundario, arma un nuevo registro y lo mete en el hash.
 		 */
 		void ingresar(TipoStruct * reg) throw(ExcepArchCerrado,ExcepRegExistente, ExcepBloqueTam);
		
		/*
		 * Quitar: Dado un registro del archivo principal, toma los campos necesarios y elimina
		 * la entrada del indice secundario.
		 */
		void quitar(TipoStruct* reg) throw(ExcepArchCerrado);
		
		/*
		 * Consultar: Toma un vector de consultas, revisa q se consulte por el campo con el
		 * cual indexa el secundario, busca todos los regs q cumplan con ese criterio y los devuelve.
		 * Si no encontro ninguno devuelve el vector vacio.
		 * Devuelve true si se consulto por campo clave de reg secundario, false en caso contrario.
		 */
		bool consultar(std::vector<ParesDatos*> &consultas, std::vector<TipoStruct*> &resultado)
									 throw(ExcepArchCerrado,ExcepLeerBloque);
									 
		/*
 		 * Devuelve la cantidad de registros del archivo de datos
 		 */ 										
 		unsigned int get_cant_regs() throw(ExcepArchCerrado);
 		
 		/*
 		 * Devuelve el tamano ocupado por el archivo, en bytes
 		 */ 
 		virtual long get_tam() throw(ExcepArchCerrado);
		
 	private:
 	
 		/*
 		 * Dado un formato de archivo valido, genera el del archivo hash
 		 * interno.
 		 */
 		std::string generar_formato_hash(const std::string &formato);
 		
 		/*
 		 * Dado un formato de archivo valido, genera el del archivo de overflow
 		 * interno.
 		 */
 		std::string generar_formato_oflow(const std::string &formato);
 		
 		/*
 		 * Dado un registro con formato de hash, arma una consulta y busca
 		 * en el archivo de hash interno. Devuelve el reg encontrado, NULL
 		 * si no lo encontro.
 		 */
 		TipoStruct* buscar_en_hash(TipoStruct* reg_hash);
 		
 		/*
 		 * Dado un registro con formato de hash, quita el reg en el archivo
 		 * de has interno.
 		 */
 		void quitar_en_hash (TipoStruct* reg_hash);
 		
 		/*
 		 * Genera un reg hash a partir de un vector de consultas.
 		 * Busca el campo por el cual indexa el ind secundario y si lo encuentra
 		 * arma el reg y lo devuelve. Sino devuelve NULL.
 		 */
 		TipoStruct* generar_reg_hash(std::vector<ParesDatos*> &consultas);
 		
 		/*
 		 * Genera un reg hash a partir de otro registro, copiando el campo
 		 * por el cual indexa el ind secundario . Como num bloque pone el pasado
 		 * por param.
 		 */
 		TipoStruct* generar_reg_hash(TipoStruct* reg, int num_bloque);
 		
 		/*
 		 * Genera un registro de tipo overflow, copiando el campo 0
 		 * del registro pasado por param.
 		 */
 		TipoStruct* generar_reg_oflow(TipoStruct* reg);
 		
 		/*
 		 * Crea los archivos internos de hash y overflow.
 		 */
 		void crear_archivos_propios();
		
};

#endif

